/*
 * 础光实时操作系统PhotonRTOS -- 环形队列
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: RUi yang<yangrui@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <photon/ring_queue.h>

uint32_t ring_get_free_size(struct ring * ring_info)
{
    uint32 freesize = ring_info->length - ring_get_used_size(ring_info);
    return freesize;
}

uint32_t ring_get_used_size(struct ring * ring_info)
{
    if (ring_info->tail > ring_info->head) {
        return ring_info->tail - ring_info->head;
    } else if (ring_info->tail < ring_info->head) {
        return ring_info->tail - ring_info->head + ring_info->length;
    }
        
    if (ring_info->tail == ring_info->head) {
        if (ring_info->isFull) {
            return ring_info->length;
        } else {
            return 0;
        }
    }
        
    return 0;
}

uint32_t ring_get_size(struct ring * ring_info)
{
    return ring_info->length;
}

void ring_set_lost_data_flag(struct ring * ring_info, bool lost_data_flag)
{
    ring_info->lostData = lost_data_flag;
}

bool ring_get_lost_data_flag(struct ring * ring_info)
{
    return ring_info->lostData;
}

uint8_t ring_push_element(struct ring * ring_info, uint8_t * data, uint32_t size)
{
    uint8_t * ring_data_buf = ring_info->data;
    uint32_t size_bak = 0;

    while (size_bak < size) {
        ring_data_buf[ring_info->tail] = data[size_bak];
        size_bak++;
        ring_info->tail++;
        ring_info->tail = ring_info->tail % ring_info->length;
    }

    if (ring_info->tail == ring_info->head) {
        ring_info->isFull = true;
    }

    return 0;
}

uint8_t ring_pop_element(struct ring * ring_info,  uint8_t * data, uint32_t size)
{
    uint8_t * ring_data_buf = ring_info->data;
    uint32_t size_bak = 0;

    ring_info->isFull = false;
    while (size_bak < size) {
        data[size_bak] = ring_data_buf[ring_info->head];
        size_bak++;
        ring_info->head ++;
        ring_info->head = ring_info->head % ring_info->length; 
    }

    return 0;
}

void ring_empty(struct ring * ring_info)
{
    ring_info->head = 0;
    ring_info->tail = 0;
    ring_info->isFull = false;
    ring_info->lostData = false;
}